#pragma once
//#include "stdafx.h"
#include "LPSmodel.h"
#include <stdio.h>      /* printf, NULL */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */
namespace LPS
{
	using namespace org::spark::core;
	using namespace org::spark::data;
	using namespace org::spark::space;
	using namespace org::spark::math;
double LPSmodel::LPSEvap = 0;
double LPSmodel::LPS1stDose = 0;
double LPSmodel::LPS1stDuration = 0;
double LPSmodel::LPS1stTime = 0;
double LPSmodel::LPS2ndDose = 0;
double LPSmodel::LPS2ndDuration = 0;
double LPSmodel::LPS2ndTime = 0;
double LPSmodel::macActLPS = 0;
double LPSmodel::macActPro = 0;
double LPSmodel::macRegen = 0;
double LPSmodel::macAge = 0;
double LPSmodel::macActDam = 0;
double LPSmodel::maxProDam = 0;
double LPSmodel::proDamThresh = 0;
double LPSmodel::damageEvap = 0;
double LPSmodel::antiHealThresh = 0;
double LPSmodel::macAnti = 0;
double LPSmodel::antiEvap = 0;
double LPSmodel::proEvap = 0;
double LPSmodel::macProp = 0;
double LPSmodel::totalLPS = 0;
double LPSmodel::proDam = 0;
double LPSmodel::totalMac = 0;
double LPSmodel::totalAm = 0;
double LPSmodel::totalAnti = 0;
double LPSmodel::totalDamage = 0;
double LPSmodel::totalPro = 0;
Grid *LPSmodel::LPS = 0;
Grid *LPSmodel::pro = 0;
Grid *LPSmodel::anti = 0;
Grid *LPSmodel::damage = 0;
double LPSmodel::step = 0;
double LPSmodel::time = 0;

	void LPSmodel::_init()
	{
		srand(( unsigned )time);
		LPSmodel::LPS = Observer::getDefaultSpace()->addDataLayer("LPS", GridFactory::createGrid(static_cast<int>((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getXSize()), static_cast<int>((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getYSize())));
		LPSmodel::pro = Observer::getDefaultSpace()->addDataLayer("pro", GridFactory::createGrid(static_cast<int>((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getXSize()), static_cast<int>((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getYSize())));
		LPSmodel::anti = Observer::getDefaultSpace()->addDataLayer("anti", GridFactory::createGrid(static_cast<int>((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getXSize()), static_cast<int>((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getYSize())));
		LPSmodel::damage = Observer::getDefaultSpace()->addDataLayer("damage", GridFactory::createGrid(static_cast<int>((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getXSize()), static_cast<int>((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getYSize())));
	}

	void LPSmodel::setup()
	{
		GridSpace *__space = new GridSpace(-60.0, 60.0, -60.0, 60.0, true, true);
		Observer::getInstance()->addSpace("space", __space);
		_init();
		double _tmpto1 = ((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getXMax() - 0.5);
		double _tmpstep1 = 1.0;

		for (double x = ((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getXMin() + 0.5); x <= _tmpto1; x += _tmpstep1)
		{

			double _tmpto = ((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getYMax() - 0.5);
			double _tmpstep = 1.0;

			for (double y = ((static_cast<BoundedSpace*>(Observer::getDefaultSpace()))->getYMin() + 0.5); y <= _tmpto; y += _tmpstep)
			{

				patch *_object = new patch();
				if (_object != 0)
				{
					patch *__agent4 = _object;
					Vector *p=new Vector(x, y, 0.0);
					__agent4->jump((p));
					//__agent4->setColor((Vector((250.0 / 255.0), (250.0 / 255.0), (210.0 / 255.0))));
				}
			}
		}
		LPSmodel::totalMac = 0.0;
		LPSmodel::totalAm = 0.0;
		LPSmodel::proDam = 0.0;
		LPSmodel::step = 0.0;
		LPSmodel::LPS->setValue(0.0);
		LPSmodel::damage->setValue(0.0);
		int _nn = static_cast<int>((LPSmodel::macRegen * 3.0));
		mac** _objects=new mac*[_nn];
		for (int _i = 0; _i < _nn; _i++)
		{
			_objects[_i] = new mac();
		}
		if (_objects != 0)
		{
			for (int _i1 = 0; _i1 < sizeof(_objects) / sizeof(_objects[0]); _i1++)
			{
				mac *__agent2 = _objects[_i1];
				//__agent2->setColor((Vector(204.0 / 255.0, 102.0 / 255.0, 0)));
				__agent2->jump(20.0);
				__agent2->jump(fRand(0.0,50.0));
				__agent2->age = (fRand(0.0,40.0) + LPSmodel::macAge);
				__agent2->activated = false;
			}
		}
	}

	bool LPSmodel::begin(long long tick)
	{
		LPSmodel::LPS->diffuse(1.0);
		LPSmodel::pro->diffuse(1.0);
		LPSmodel::anti->diffuse(1.0);
		LPSmodel::damage->diffuse(1.0);
		if ((5.0 > fRand(0.0,100.0)))
		{
			double newmac = 0;

			newmac = floor(fRand(0.0,LPSmodel::macRegen));
			int _nn = static_cast<int>(newmac);
			mac** _objects=new mac*[_nn];
			for (int _i = 0; _i < _nn; _i++)
			{
				_objects[_i] = new mac();
			}
			if (_objects != 0)
			{
				for (int _i1 = 0; _i1 < sizeof(_objects) / sizeof(_objects[0]); _i1++)
				{
					mac *__agent3 = _objects[_i1];
					//__agent3->setColor((Vector(204.0 / 255.0, 102.0 / 255.0, 0)));
					__agent3->jump(20.0);
					__agent3->jump(fRand(0.0,50.0));
					__agent3->age = (fRand(0.0,50.0) + LPSmodel::macAge);
					__agent3->activated = false;
				}
			}
		}
		if (((tick % 2) == 0.0))
		{
			std::vector<mac*> _result = Observer::getInstance()->getAgentsList(new mac());
			if (_result.size() > 0)
			{
				for (int _i2 = 0; _i2 < _result.size(); _i2++)
				{
					mac *__agent3 = _result[_i2];
					__agent3->macFunction();
				}
			}
			std::vector<am*> _result1 = Observer::getInstance()->getAgentsList(new am());
			if (_result1.size() > 0)
			{
				for (int _i3 = 0; _i3 < _result1.size(); _i3++)
				{
					am *__agent3 = _result1[_i3];
					__agent3->amFunction();
				}
			}
			LPSmodel::LPS->multiply(LPSmodel::LPSEvap);
			LPSmodel::pro->multiply(LPSmodel::proEvap);
			LPSmodel::anti->multiply(LPSmodel::antiEvap);
			LPSmodel::damage->multiply(LPSmodel::damageEvap);
			std::vector<patch*> _result2 = Observer::getInstance()->getAgentsList(new patch());
			if (_result2.size() > 0)
			{
				for (int _i4 = 0; _i4 < _result2.size(); _i4++)
				{
					patch *__agent3 = _result2[_i4];
					__agent3->causeDamage();
				}
			}
			this->updateSystem();
		}
		if (((tick >= LPSmodel::LPS1stTime) && (tick <= (LPSmodel::LPS1stTime + LPSmodel::LPS1stDuration))))
		{
			std::vector<patch*> _result3 = Observer::getInstance()->getAgentsList(new patch());
			if (_result3.size() > 0)
			{
				for (int _i5 = 0; _i5 < _result3.size(); _i5++)
				{
					patch *__agent3 = _result3[_i5];
					if ((__agent3->getPosition()->length() < 10.0))
					{
						LPSmodel::LPS->setValue(__agent3, LPSmodel::LPS1stDose);
					}
				}
			}
		}
		if (((tick >= LPSmodel::LPS2ndTime) && (tick <= (LPSmodel::LPS2ndTime + LPSmodel::LPS2ndDuration))))
		{
			std::vector<patch*> _result4 = Observer::getInstance()->getAgentsList(new patch());
			if (_result4.size() > 0)
			{
				for (int _i6 = 0; _i6 < _result4.size(); _i6++)
				{
					patch *__agent3 = _result4[_i6];
					if ((__agent3->getPosition()->length() < 10.0))
					{
						LPSmodel::LPS->setValue(__agent3, LPSmodel::LPS2ndDose);
					}
				}
			}
		}
		return false;
	}

	bool LPSmodel::end(long long tick)
	{
		if ((Observer::getInstance()->getAgentsNumberOfKind(new CellAgent()) > 50000.0))
		{
			return true;
		}
		return false;
	}

	void LPSmodel::updateSystem()
	{
		LPSmodel::totalLPS = LPSmodel::LPS->getTotalNumber();
		LPSmodel::totalPro = LPSmodel::pro->getTotalNumber();
		LPSmodel::totalAnti = LPSmodel::anti->getTotalNumber();
		LPSmodel::totalDamage = LPSmodel::damage->getTotalNumber();
		LPSmodel::totalAm = Observer::getInstance()->getAgentsNumber(new am());
		LPSmodel::totalMac = Observer::getInstance()->getAgentsNumber(new am());
	}

	void LPSmodel::addLPS()
	{
		//std::vector v0 = std::vector();
		//std::vector v = std::vector();
		double iter = 0;
		double j = 0;
		double i = 0;

		i = fRand(-60.0, 60.0);
		j = fRand(-60.0, 60.0);
		iter = 15.0;
		std::vector<patch*> _result = Observer::getInstance()->getAgentsList(new patch());
		if (_result.size() > 0)
		{
			for (int _i = 0; _i < _result.size(); _i++)
			{
				patch *__agent2 = _result[_i];
				if ((__agent2->getPosition()->length() < 5.0))
				{
					LPSmodel::LPS->setValue(__agent2, LPSmodel::LPS1stDose);
				}
			}
		}
	}

	double LPSmodel::get_LPSEvap()
	{
		return LPSEvap;
	}

	void LPSmodel::set_LPSEvap(double value)
	{
		LPSEvap = value;
	}

	double LPSmodel::get_LPS1stDose()
	{
		return LPS1stDose;
	}

	void LPSmodel::set_LPS1stDose(double value)
	{
		LPS1stDose = value;
	}

	double LPSmodel::get_LPS1stDuration()
	{
		return LPS1stDuration;
	}

	void LPSmodel::set_LPS1stDuration(double value)
	{
		LPS1stDuration = value;
	}

	double LPSmodel::get_LPS1stTime()
	{
		return LPS1stTime;
	}

	void LPSmodel::set_LPS1stTime(double value)
	{
		LPS1stTime = value;
	}

	double LPSmodel::get_LPS2ndDose()
	{
		return LPS2ndDose;
	}

	void LPSmodel::set_LPS2ndDose(double value)
	{
		LPS2ndDose = value;
	}

	double LPSmodel::get_LPS2ndDuration()
	{
		return LPS2ndDuration;
	}

	void LPSmodel::set_LPS2ndDuration(double value)
	{
		LPS2ndDuration = value;
	}

	double LPSmodel::get_LPS2ndTime()
	{
		return LPS2ndTime;
	}

	void LPSmodel::set_LPS2ndTime(double value)
	{
		LPS2ndTime = value;
	}

	double LPSmodel::get_macActLPS()
	{
		return macActLPS;
	}

	void LPSmodel::set_macActLPS(double value)
	{
		macActLPS = value;
	}

	double LPSmodel::get_macActPro()
	{
		return macActPro;
	}

	void LPSmodel::set_macActPro(double value)
	{
		macActPro = value;
	}

	double LPSmodel::get_macRegen()
	{
		return macRegen;
	}

	void LPSmodel::set_macRegen(double value)
	{
		macRegen = value;
	}

	double LPSmodel::get_macAge()
	{
		return macAge;
	}

	void LPSmodel::set_macAge(double value)
	{
		macAge = value;
	}

	double LPSmodel::get_macActDam()
	{
		return macActDam;
	}

	void LPSmodel::set_macActDam(double value)
	{
		macActDam = value;
	}

	double LPSmodel::get_maxProDam()
	{
		return maxProDam;
	}

	void LPSmodel::set_maxProDam(double value)
	{
		maxProDam = value;
	}

	double LPSmodel::get_proDamThresh()
	{
		return proDamThresh;
	}

	void LPSmodel::set_proDamThresh(double value)
	{
		proDamThresh = value;
	}

	double LPSmodel::get_damageEvap()
	{
		return damageEvap;
	}

	void LPSmodel::set_damageEvap(double value)
	{
		damageEvap = value;
	}

	double LPSmodel::get_antiHealThresh()
	{
		return antiHealThresh;
	}

	void LPSmodel::set_antiHealThresh(double value)
	{
		antiHealThresh = value;
	}

	double LPSmodel::get_macAnti()
	{
		return macAnti;
	}

	void LPSmodel::set_macAnti(double value)
	{
		macAnti = value;
	}

	double LPSmodel::get_antiEvap()
	{
		return antiEvap;
	}

	void LPSmodel::set_antiEvap(double value)
	{
		antiEvap = value;
	}

	double LPSmodel::get_proEvap()
	{
		return proEvap;
	}

	void LPSmodel::set_proEvap(double value)
	{
		proEvap = value;
	}

	double LPSmodel::get_macProp()
	{
		return macProp;
	}

	void LPSmodel::set_macProp(double value)
	{
		macProp = value;
	}

	double LPSmodel::get_totalLPS()
	{
		return totalLPS;
	}

	void LPSmodel::set_totalLPS(double value)
	{
		totalLPS = value;
	}

	double LPSmodel::get_proDam()
	{
		return proDam;
	}

	void LPSmodel::set_proDam(double value)
	{
		proDam = value;
	}

	double LPSmodel::get_totalMac()
	{
		return totalMac;
	}

	void LPSmodel::set_totalMac(double value)
	{
		totalMac = value;
	}

	double LPSmodel::get_totalAm()
	{
		return totalAm;
	}

	void LPSmodel::set_totalAm(double value)
	{
		totalAm = value;
	}

	double LPSmodel::get_totalAnti()
	{
		return totalAnti;
	}

	void LPSmodel::set_totalAnti(double value)
	{
		totalAnti = value;
	}

	double LPSmodel::get_totalDamage()
	{
		return totalDamage;
	}

	void LPSmodel::set_totalDamage(double value)
	{
		totalDamage = value;
	}

	double LPSmodel::get_totalPro()
	{
		return totalPro;
	}

	void LPSmodel::set_totalPro(double value)
	{
		totalPro = value;
	}

	double LPSmodel::get_step()
	{
		return step;
	}

	void LPSmodel::set_step(double value)
	{
		step = value;
	}

	double LPSmodel::get_time()
	{
		return time;
	}

	void LPSmodel::set_time(double value)
	{
		time = value;
	}
	double fRand(double fMin, double fMax)
	{
				double f = (double)rand() / 1+RAND_MAX;
				return fMin + f * (fMax - fMin);
	}
}
